import json
import logging
import logging.config
import os
import uuid
from typing import Annotated

import orjson
from fastapi import FastAPI, HTTPException, WebSocketException
from fastapi.openapi.docs import get_swagger_ui_html, get_redoc_html
from fastapi.responses import ORJSONResponse
from pymilvus import MilvusException
from starlette import status
from starlette.websockets import WebSocket

from app.core.config import settings
from app.exception.FunCallError import FunCallError
from app.schemas.result import errResult
from app.startup.migarate import DatabaseMigrator
from app.utils.str_utils import str_prominent


def initLogging():
    # fname = settings.get_logging_conf_name_path()
    fname = settings.get_alembic_int_path()
    print(str_prominent(fname))

    # 打开文件并指定使用 UTF-8 编码
    with open(fname, 'r', encoding='utf-8') as f:
        # logging.basicConfig(level=logging.DEBUG)
        logging.config.fileConfig(f, defaults=None, disable_existing_loggers=True)
    # logging.getLogger('sqlalchemy.engine').setLevel(logging.DEBUG)
initLogging()

from app.api.api_v1.api import api_router


app = FastAPI(
    title=settings.PROJECT_NAME,
    version=settings.VERSION,
    openapi_url=f"{settings.API_V1_STR}/openapi.json",
)
# app.json_provider.json_encoder  = DateEncoder
# app.json_provider = {
#     'dumps': json_encoder.dumps,
#     'loads': orjson.loads
# }

app.include_router(api_router, prefix=settings.API_V1_STR)

print(str_prominent('startup'))
@app.on_event("startup")
async def startup_event():
    print('startup_event')
    from app.startup import init_or_startup
    init_or_startup()
    # Run database migrations
    migrator = DatabaseMigrator(settings.get_database_url)
    migrator.run_migrations()
    from app.startup.init_data import DatabaseInitData
    DatabaseInitData(settings.get_database_url).startup()


@app.get("/")
async def root():
    return {"message": "欢迎使用AI程序员API"}


@app.get("/api/health")
async def health_check():
    return {
        "status": "healthy",
        "version": settings.VERSION,
    }


# 自定义/docs路由以使用Swagger UI（如果需要的话）
@app.get("/docs", include_in_schema=False)  # include_in_schema=False防止在OpenAPI文档中显示此路由
async def custom_swagger_ui_html():
    return get_swagger_ui_html(openapi_url=app.openapi(), title="My API with Custom Title")


# 自定义/redoc路由以使用ReDoc（如果需要的话）
@app.get("/redoc", include_in_schema=False)  # include_in_schema=False防止在OpenAPI文档中显示此路由
async def redoc_html():
    return get_redoc_html(openapi_url=app.openapi())


@app.get("/hello/{name}")
async def say_hello(name: str):
    return {"message": f"Hello {name}"}


from fastapi import Depends, Body
from pydantic import BaseModel


class Item(BaseModel):
    name: str | None = None
    description: str | None = None
    price: float | None = None
    tax: float | None = None


@app.post("/test/post/json")
async def create_item(item: Item = Body()):
    print("/test/post/json")
    # print(json.dumps(item.__dict__))
    return item


#https://blog.csdn.net/qq839019311/article/details/139993815
# async def authenticate(
#         websocket: WebSocket,
#         userid: str,
#         secret: str,
# ):
#     if userid is None or secret is None:
#         raise WebSocketException(code=status.WS_1008_POLICY_VIOLATION)
#
#     print(f'userid: {userid},secret: {secret}')
#     if '12345' == userid and 'xxxxxxxxxxxxxxxxxxxxxxxxxx' == secret:
#         return 'pass'
#     else:
#         return 'fail'
#
# @app.websocket("/ws")
# async def websocket_endpoint(*, websocket: WebSocket, userid: str, permission: Annotated[str, Depends(authenticate)], ):
#     await websocket.accept()
#     while True:
#         text = await websocket.receive_text()
#
#         if 'fail' == permission:
#             await websocket.send_text(
#                 f"authentication failed"
#             )
#         else:
#             await websocket.send_text(f"receive message from: {userid}， text was: {text}")


from fastapi import Request



@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException = Depends(HTTPException)):
    from fastapi.responses import JSONResponse
    return JSONResponse(
        status_code=500,
        content=errResult(
            code=exc.status_code,
            msg=exc.detail
        ).json_encoders()
    )


@app.exception_handler(MilvusException)
async def milvus_exception_handler(request: Request, exc: MilvusException = Depends(MilvusException)):
    from fastapi.responses import JSONResponse
    message = exc.message
    if exc.code == 2:
        message = '连接错误[1.连接参数无效或服务器不可用,2.连接超时]\n' + message
    if exc.code == 65535:
        message = '数据长度错误‌\n' + message
    return JSONResponse(
        status_code=500,
        content=errResult(
            code=exc.code,
            msg=message
        ).json_encoders()
    )


@app.exception_handler(FunCallError)
async def funcall_error_handler(request: Request, exc: FunCallError = Depends(FunCallError)):
    from fastapi.responses import JSONResponse
    message = exc.message
    return JSONResponse(
        status_code=500,
        content=errResult(
            code=500,
            msg=message
        ).json_encoders()
    )

